﻿
#region Copyright & License
// --------------------------
// Copyright 2008 Daniel Gray
// --------------------------
// This file is part of Kale.
//
// Kale is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Kale is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Kale.  If not, see <http://www.gnu.org/licenses/>.
#endregion
#region File details
// --------------------------------------------------------
// Filename          : ImageNode.cs
// Author            : Daniel Gray
// Created           : 15/04/2008
// --------------------------------------------------------
#endregion
            
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;

namespace Kale.Core
{
   public class ImageNode : IImageNode
   {
      private NodeId _nodeId;
      private NodeType _nodeType;
      private string _nodePath;
      private string _name;
      private List<IImageNode> _children;
      private IImageNode _parent;
      private bool _isStale = false;
      private object _childrenLock = new object();

      private INodeProvider _factory;

      public ImageNode(NodeId nodeId, NodeType nodeType, string nodePath, string name, INodeProvider factory)
      {
         _nodeId = nodeId;
         _nodeType = nodeType;
         _nodePath = nodePath;
         _name = name;
         _factory = factory;
      }

      private void RefreshStaleChildren()
      {
         IImageNode[] staleChildren = _children.Where(c => c.IsStale).ToArray();

         if (staleChildren.Length > 0)
         {
            foreach (IImageNode staleChild in staleChildren)
            {
               _children.Remove(staleChild);

               // reload

               IImageNode refreshedChild = _factory.LoadNode(staleChild.NodeId);

               if (refreshedChild != null)
               {
                  _children.Add(refreshedChild);
               }
            }
         }
      }

      #region IImageNode Members

      public NodeId NodeId
      {
         get { return _nodeId; }
      }

      public NodeType NodeType
      {
         get { return _nodeType; }
      }

      public FileSystemInfo NodeInformation
      {
         get
         {
            if (string.IsNullOrEmpty(_nodePath)) return null;

            if (NodeType == NodeType.File)
            {
               return new FileInfo(_nodePath);
            }
            else
            {
               return new DirectoryInfo(_nodePath);
            }
         }
      }

      public string Name
      {
         get { return _name; }
      }

      public IImageNode[] Children
      {
         get 
         {
            lock (_childrenLock)
            {
               if (_children == null)
               {
                  _children = new List<IImageNode>(_factory.LoadChildren(NodeId));
               }

               RefreshStaleChildren();

               return _children.ToArray();
            }
         }
      }

      public IImageNode Parent
      {
         get 
         {
            if (_parent == null)
            {
               _parent = _factory.LoadParent(NodeId);
            }

            return _parent;
         }
      }

      public Image OpenImage()
      {
         if (NodeType == NodeType.Folder)
         {
            throw new InvalidOperationException("Not a file.");
         }

         return Image.FromFile(NodeInformation.FullName);
      }

      public bool IsStale
      {
         get { return _isStale; }
      }

      public void MakeStale(NodeStaleReason reason)
      {
         _isStale = true;

         OnStale(reason);
      }

      public event EventHandler<NodeStaleEventArgs> Stale;

      #endregion

      protected virtual void OnStale(NodeStaleReason reason)
      {
         NodeStaleEventArgs e = new NodeStaleEventArgs(reason);

         EventHandler<NodeStaleEventArgs> eh = Stale;

         if (eh != null) eh(this, e);
      }
   }
}
